package com.xsy.glsurfaceview

import android.opengl.GLES30
import android.opengl.Matrix
import android.util.Log
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.FloatBuffer

class Triangle(vertexShaderCode: String, fragmentShaderCode: String) {
    companion object{
        const val vertex_file_path = "vshader/Triangle.glsl"
        const val fragment_file_path = "fshader/Triangle.glsl"
    }
    private val triangleCoordinate = floatArrayOf(
        -0.5f, 0.5f, 0.0f, //0
        -0.5f, -0.5f, 0.0f,//1
        0.5f, -0.5f, 0.0f,//2
        0.5f, 0.5f, 0.0f//3
    )

    private var translateMatrix = FloatArray(16)
    private val color = floatArrayOf(0.5f, 0.5f, 0.5f, 1.0f)

    private var mProgram = 0
    private var mPositionHandle = 0
    private var mColorHandle = 0
    private var mTMatrixHandle = 0
    private var vertexBuffer: FloatBuffer
    private val vboIds: IntArray = IntArray(1)
    private val eboIds: IntArray = IntArray(1)
    private var indecs = intArrayOf(0, 1, 2, 2, 3, 0)
    private fun loadShader(type: Int, shaderCode: String): Int {
        val shader = GLES30.glCreateShader(type)
        GLES30.glShaderSource(shader, shaderCode)
        GLES30.glCompileShader(shader)
        return shader
    }

    init {
        val bb = ByteBuffer.allocateDirect((triangleCoordinate.size * 4))
        bb.order(ByteOrder.nativeOrder())
        vertexBuffer = bb.asFloatBuffer()
        vertexBuffer.put(triangleCoordinate)
        vertexBuffer.position(0)

        val indexBuffer = ByteBuffer.allocateDirect(indecs.size * 4)
            .order(ByteOrder.nativeOrder())
            .asIntBuffer()
        indexBuffer.put(indecs)
        indexBuffer.position(0)


        Matrix.setIdentityM(translateMatrix, 0)
//        Matrix.rotateM(translateMatrix, 0,1.0f, 90.0f, 1.0f, 1.0f )
//        Matrix.setRotateM(translateMatrix, 0, 90.0f, 0.0f, 1.0f, 1.0f)
        Matrix.scaleM(translateMatrix, 0, 0.5f, 0.5f, 1.0f)
        //Matrix.translateM(translateMatrix, 0, 0.5f, 0f, 0f)

        val vertexShader = loadShader(GLES30.GL_VERTEX_SHADER, vertexShaderCode)
        val fragmentShader = loadShader(GLES30.GL_FRAGMENT_SHADER, fragmentShaderCode)
        mProgram = GLES30.glCreateProgram()
        GLES30.glAttachShader(mProgram, vertexShader)
        GLES30.glAttachShader(mProgram, fragmentShader)
        GLES30.glLinkProgram(mProgram)

        GLES30.glGenBuffers(1, vboIds, 0)
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vboIds[0])
        GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER, bb.capacity(), bb, GLES30.GL_STATIC_DRAW)
        Log.d("MyGLSurfaceView", "bb.capacity(): ${bb.capacity()}")
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0)

        GLES30.glGenBuffers(1, eboIds, 0)
        GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, eboIds[0])
        GLES30.glBufferData(
            GLES30.GL_ELEMENT_ARRAY_BUFFER,
            indexBuffer.capacity() * 4,
            indexBuffer,
            GLES30.GL_STATIC_DRAW
        )
        Log.d("MyGLSurfaceView", "indexBuffer.capacity(): ${indexBuffer.capacity()}")
        GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, 0)

    }

    fun draw() {
        GLES30.glUseProgram(mProgram)
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vboIds[0])
        GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, eboIds[0])
        mPositionHandle = GLES30.glGetAttribLocation(mProgram, "vPosition")
        GLES30.glEnableVertexAttribArray(mPositionHandle)
        GLES30.glVertexAttribPointer(mPositionHandle, 3, GLES30.GL_FLOAT, false, 0, 0)
        mTMatrixHandle = GLES30.glGetUniformLocation(mProgram, "mTMatrix")
        GLES30.glUniformMatrix4fv(mTMatrixHandle, 1, false, translateMatrix, 0)

        mColorHandle = GLES30.glGetUniformLocation(mProgram, "vColor")
        GLES30.glUniform4fv(mColorHandle, 1, color, 0)
//        GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, 3)
        GLES30.glDrawElements(GLES30.GL_TRIANGLES, indecs.size, GLES30.GL_UNSIGNED_INT, 0)
        GLES30.glDisableVertexAttribArray(mPositionHandle)
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0)
        GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, 0)
    }

}